/*
ZhouSolver.c
Based on code posted to <http://forum.enjoysudoku.com/3-77us-solver-2-8g-cpu-testcase-17sodoku-t30470.html>
by user zhouyundong_2012.
The copyright is not specified.
*/
#define _CRT_SECURE_NO_DEPRECATE
#include <string.h>
#include <ctype.h>
#include <stdio.h>

// added for debugging and generation purpose ===============
#include <fstream>
#include <iostream>
#include <stdlib.h>
using namespace std;
#include "v2t_128.h"
#include "v2bitfields.h"
#include "v2utilities.h"
#include "v2sk_tables.h"
#include "v2solver_step.h"
extern PM_GO pm_go;
//extern OPTIONS options;
//====================================
#include "v2ZhouSolver.h"


int TblSelfMask27[27] = {
0x37E3F001,0x37E3F002,0x37E3F004,0x371F8E08,0x371F8E10,0x371F8E20,0x30FC7E40,0x30FC7E80,0x30FC7F00,
0x2FE003F8,0x2FE005F8,0x2FE009F8,0x2F1C11C7,0x2F1C21C7,0x2F1C41C7,0x28FC803F,0x28FD003F,0x28FE003F,
0x1807F1F8,0x180BF1F8,0x1813F1F8,0x18238FC7,0x18438FC7,0x18838FC7,0x19007E3F,0x1A007E3F,0x1C007E3F,
};

int TblBoxMask[3] = {0x1c0e07,0xe07038,0x70381c0 };
// F[27] is digit + band (9 times 3 bits per digit)
//   bit content is a 27 cells map

GAME game[100]; // must host main brute force plus minimality analysis and recursive generation
GAME Tblgame;//================== initial for a GAME

GAME::GLOBAL   GAME::glb;   // global variables for the class GAME

GAME::GLOBAL::GLOBAL(){
	mytable=game;

	cout <<"check create tables"<<endl;
	// init Tblgame
	Tblgame.index=0;
	for(int i=0;i<3;i++) Tblgame.BlockMaskSum[i]=0;
	for(int i=0;i<27;i++){
		Tblgame.F[i] = BIT_SET_30;
		Tblgame.CompF[i] = Tblgame.BlockMask[i] =0;
	}
}

void GAME::InitSudoku(const char * ze, int indexe){
	(*this)=Tblgame;
	index=indexe;
	for (int i=0;i<81;i++)   {
		 byte wc=ze[i];
		 int offset=Tbloffset[i];
		 if(wc<'1' || wc > '9') continue;
		 int B = TblMult3[wc - '1'] + TblBoard_Block[i];
		 //Get BlockMask and Sum of BlockMask
		 BlockMaskSum[TblBoard_Block[i]] |= TblBoard_BlockMask27[offset];
		 BlockMask[B] |= TblBoard_BlockMask27[offset];
		 //Self and Another Block
		 F[B] &= TblSelfMask27[offset];
		 F[TblAnother1[B]] &= TblOtherMask9[TblMod9[offset]];
		 F[TblAnother2[B]] &= TblOtherMask9[TblMod9[offset]];
	 }
	 BlockMaskSum[0] ^= BIT_SET_30;
	 BlockMaskSum[1] ^= BIT_SET_30;
	 BlockMaskSum[2] ^= BIT_SET_30;
	 for(int i=0;i<27;i++)
		  F[i] &= BlockMaskSum[i%3] ^ BlockMask[i];
//	Debug();
}

#define UPD(X,Y,Z) \
Shrink = (TblShrinkMask[F[X] & 0x1FF] | \
TblShrinkMask[ (F[X]>>9) & 0x1FF]<<3 | \
TblShrinkMask[ (F[X]>>18) & 0x1FF]<<6);	\
if ((F[X] &=TblComplexMask[Shrink]) ==0)    return 0; \
S = ((F[X] | (F[X] >> 9) | (F[X] >> 18)) & 0x1FF);  \
C1= S | ((F[Y] | (F[Y] >> 9) | (F[Y] >> 18)) & 0x1FF); \
C2= S | ((F[Z] | (F[Z] >> 9) | (F[Z] >> 18)) & 0x1FF); \
F[Z] &= TblMaskSingle[S] & TblMaskDouble[C1]; \
F[Y] &= TblMaskSingle[S] & TblMaskDouble[C2]; \
S = TblRowUniq[TblShrinkSingle[Shrink] & TblColumnSingle[S]];

 int GAME::Update(){
  int Shrink=1,S,C1,C2,cl;
  while(Shrink){ 
 	Shrink=0;
 	if (CompF[0] != F[0] && F[0]>>27) {	UPD(0,1,2)
		if((F[0] >> 27) != S) { //  new single(s) not a key sequence
			F[0] &= S << 27 | BIT_SET_27; 	cl = ~(F[0] & TblRowMask[S]);
			F[3] &= cl; F[6] &= cl; F[9] &= cl; F[12] &= cl;F[15] &= cl; F[18] &= cl;F[21] &= cl;F[24] &= cl;
		}
		CompF[0] = F[0];
	}		 
 	if (CompF[1] != F[1] && F[1]>>27) {		UPD(1,0,2)
		if((F[1] >> 27) != S) { //  new single(s) not a key sequence
			F[1] &= S << 27 | BIT_SET_27; 			cl = ~(F[1] & TblRowMask[S]);
			F[4] &= cl; F[7] &= cl; F[10] &= cl; F[13] &= cl;F[16] &= cl; F[19] &= cl;F[22] &= cl;F[25] &= cl;
		}
		CompF[1] = F[1];
	}		 
 	if (CompF[2] != F[2] && F[2]>>27) {	UPD(2,1,0)
		if((F[2] >> 27) != S) { //  new single(s) not a key sequence
			F[2] &= S << 27 | BIT_SET_27; 			cl = ~(F[2] & TblRowMask[S]);
			F[5] &= cl; F[8] &= cl; F[11] &= cl; F[14] &= cl;F[17] &= cl; F[20] &= cl;F[23] &= cl;F[26] &= cl;
		}
		CompF[2] = F[2];
	}		 
  	if (CompF[3] != F[3] && F[3]>>27) {	UPD(3,4,5)
		if((F[3] >> 27) != S) { //  new single(s) not a key sequence
			F[3] &= S << 27 | BIT_SET_27; 	cl = ~(F[3] & TblRowMask[S]);
			F[0] &= cl; F[6] &= cl; F[9] &= cl; F[12] &= cl;F[15] &= cl; F[18] &= cl;F[21] &= cl;F[24] &= cl;
		}
		CompF[3] = F[3];
	}		 
 	if (CompF[4] != F[4] && F[4]>>27) {	UPD(4,3,5)
		if((F[4] >> 27) != S) { //  new single(s) not a key sequence
			F[4] &= S << 27 | BIT_SET_27; 			cl = ~(F[4] & TblRowMask[S]);
			F[1] &= cl; F[7] &= cl; F[10] &= cl; F[13] &= cl;F[16] &= cl; F[19] &= cl;F[22] &= cl;F[25] &= cl;
		}
		CompF[4] = F[4];
	}		 
 	if (CompF[5] != F[5] && F[5]>>27) {		UPD(5,3,4)
		if((F[5] >> 27) != S) { //  new single(s) not a key sequence
			F[5] &= S << 27 | BIT_SET_27; 			cl = ~(F[5] & TblRowMask[S]);
			F[2] &= cl; F[8] &= cl; F[11] &= cl; F[14] &= cl;F[17] &= cl; F[20] &= cl;F[23] &= cl;F[26] &= cl;
		}
		CompF[5] = F[5];
	}		 
  	if (CompF[6] != F[6] && F[6]>>27) {	UPD(6,7,8)
		if((F[6] >> 27) != S) { //  new single(s) not a key sequence
			F[6] &= S << 27 | BIT_SET_27; 	cl = ~(F[6] & TblRowMask[S]);
			F[0] &= cl; F[3] &= cl; F[9] &= cl; F[12] &= cl;F[15] &= cl; F[18] &= cl;F[21] &= cl;F[24] &= cl;
		}
		CompF[6] = F[6];
	}		 
 	if (CompF[7] != F[7] && F[7]>>27) {	UPD(7,6,8)
		if((F[7] >> 27) != S) { //  new single(s) not a key sequence
			F[7] &= S << 27 | BIT_SET_27; 			cl = ~(F[7] & TblRowMask[S]);
			F[1] &= cl; F[4] &= cl; F[10] &= cl; F[13] &= cl;F[16] &= cl; F[19] &= cl;F[22] &= cl;F[25] &= cl;
		}
		CompF[7] = F[7];
	}		 
 	if (CompF[8] != F[8] && F[8]>>27) {	UPD(8,6,7)
		if((F[8] >> 27) != S) { //  new single(s) not a key sequence
			F[8] &= S << 27 | BIT_SET_27; 			cl = ~(F[8] & TblRowMask[S]);
			F[2] &= cl; F[5] &= cl; F[11] &= cl; F[14] &= cl;F[17] &= cl; F[20] &= cl;F[23] &= cl;F[26] &= cl;
		}
		CompF[8] = F[8];
	}		 
  	if (CompF[9] != F[9] && F[9]>>27) {		UPD(9,10,11)
		if((F[9] >> 27) != S) { //  new single(s) not a key sequence
			F[9] &= S << 27 | BIT_SET_27; 	cl = ~(F[9] & TblRowMask[S]);
			F[0] &= cl; F[3] &= cl; F[6] &= cl; F[12] &= cl;F[15] &= cl; F[18] &= cl;F[21] &= cl;F[24] &= cl;
		}
		CompF[9] = F[9];
	}		 
 	if (CompF[10] != F[10] && F[10]>>27) {	UPD(10,9,11)
		if((F[10] >> 27) != S) { //  new single(s) not a key sequence
			F[10] &= S << 27 | BIT_SET_27; 			cl = ~(F[10] & TblRowMask[S]);
			F[1] &= cl; F[4] &= cl; F[7] &= cl; F[13] &= cl;F[16] &= cl; F[19] &= cl;F[22] &= cl;F[25] &= cl;
		}
		CompF[10] = F[10];
	}		 
 	if (CompF[11] != F[11] && F[11]>>27) {	UPD(11,9,10)
		if((F[11] >> 27) != S) { //  new single(s) not a key sequence
			F[11] &= S << 27 | BIT_SET_27; 			cl = ~(F[11] & TblRowMask[S]);
			F[2] &= cl; F[5] &= cl; F[8] &= cl; F[14] &= cl;F[17] &= cl; F[20] &= cl;F[23] &= cl;F[26] &= cl;
		}
		CompF[11] = F[11];
	}		 
  	if (CompF[12] != F[12] && F[12]>>27) {	UPD(12,13,14)
		if((F[12] >> 27) != S) { //  new single(s) not a key sequence
			F[12] &= S << 27 | BIT_SET_27; 	cl = ~(F[12] & TblRowMask[S]);
			F[0] &= cl; F[3] &= cl; F[6] &= cl; F[9] &= cl;F[15] &= cl; F[18] &= cl;F[21] &= cl;F[24] &= cl;
		}
		CompF[12] = F[12];
	}		 
 	if (CompF[13] != F[13] && F[13]>>27) {	UPD(13,12,14)
		if((F[13] >> 27) != S) { //  new single(s) not a key sequence
			F[13] &= S << 27 | BIT_SET_27; 			cl = ~(F[13] & TblRowMask[S]);
			F[1] &= cl; F[4] &= cl; F[7] &= cl; F[10] &= cl;F[16] &= cl; F[19] &= cl;F[22] &= cl;F[25] &= cl;
		}
		CompF[13] = F[13];
	}		 
 	if (CompF[14] != F[14] && F[14]>>27) {	UPD(14,12,13)
		if((F[14] >> 27) != S) { //  new single(s) not a key sequence
			F[14] &= S << 27 | BIT_SET_27; 			cl = ~(F[14] & TblRowMask[S]);
			F[2] &= cl; F[5] &= cl; F[8] &= cl; F[11] &= cl;F[17] &= cl; F[20] &= cl;F[23] &= cl;F[26] &= cl;
		}
		CompF[14] = F[14];
	}		 
  	if (CompF[15] != F[15] && F[15]>>27) {	UPD(15,16,17)
		if((F[15] >> 27) != S) { //  new single(s) not a key sequence
			F[15] &= S << 27 | BIT_SET_27; 	cl = ~(F[15] & TblRowMask[S]);
			F[0] &= cl; F[3] &= cl; F[6] &= cl; F[9] &= cl;F[12] &= cl; F[18] &= cl;F[21] &= cl;F[24] &= cl;
		}
		CompF[15] = F[15];
	}		 
 	if (CompF[16] != F[16] && F[16]>>27) {	UPD(16,15,17)
		if((F[16] >> 27) != S) { //  new single(s) not a key sequence
			F[16] &= S << 27 | BIT_SET_27; 			cl = ~(F[16] & TblRowMask[S]);
			F[1] &= cl; F[4] &= cl; F[7] &= cl; F[10] &= cl;F[13] &= cl; F[19] &= cl;F[22] &= cl;F[25] &= cl;
		}
		CompF[16] = F[16];
	}		 
 	if (CompF[17] != F[17] && F[17]>>27) {	UPD(17,15,16)
		if((F[17] >> 27) != S) { //  new single(s) not a key sequence
			F[17] &= S << 27 | BIT_SET_27; 			cl = ~(F[17] & TblRowMask[S]);
			F[2] &= cl; F[5] &= cl; F[8] &= cl; F[11] &= cl;F[14] &= cl; F[20] &= cl;F[23] &= cl;F[26] &= cl;
		}
		CompF[17] = F[17];
	}		 
  	if (CompF[18] != F[18] && F[18]>>27) {	UPD(18,19,20)
		if((F[18] >> 27) != S) { //  new single(s) not a key sequence
			F[18] &= S << 27 | BIT_SET_27; 	cl = ~(F[18] & TblRowMask[S]);
			F[0] &= cl; F[3] &= cl; F[6] &= cl; F[9] &= cl;F[12] &= cl; F[15] &= cl;F[21] &= cl;F[24] &= cl;
		}
		CompF[18] = F[18];
	}		 
 	if (CompF[19] != F[19] && F[19]>>27) {	UPD(19,18,20)
		if((F[19] >> 27) != S) { //  new single(s) not a key sequence
			F[19] &= S << 27 | BIT_SET_27; 			cl = ~(F[19] & TblRowMask[S]);
			F[1] &= cl; F[4] &= cl; F[7] &= cl; F[10] &= cl;F[13] &= cl; F[16] &= cl;F[22] &= cl;F[25] &= cl;
		}
		CompF[19] = F[19];
	}		 
 	if (CompF[20] != F[20] && F[20]>>27) {	UPD(20,18,19)
		if((F[20] >> 27) != S) { //  new single(s) not a key sequence
			F[20] &= S << 27 | BIT_SET_27; 			cl = ~(F[20] & TblRowMask[S]);
			F[2] &= cl; F[5] &= cl; F[8] &= cl; F[11] &= cl;F[14] &= cl; F[17] &= cl;F[23] &= cl;F[26] &= cl;
		}
		CompF[20] = F[20];
	}		 
  	if (CompF[21] != F[21] && F[21]>>27) {	UPD(21,22,23)
		if((F[21] >> 27) != S) { //  new single(s) not a key sequence
			F[21] &= S << 27 | BIT_SET_27; 	cl = ~(F[21] & TblRowMask[S]);
			F[0] &= cl; F[3] &= cl; F[6] &= cl; F[9] &= cl;F[12] &= cl; F[15] &= cl;F[18] &= cl;F[24] &= cl;
		}
		CompF[21] = F[21];
	}		 
 	if (CompF[22] != F[22] && F[22]>>27) {	UPD(22,21,23)
		if((F[22] >> 27) != S) { //  new single(s) not a key sequence
			F[22] &= S << 27 | BIT_SET_27; 			cl = ~(F[22] & TblRowMask[S]);
			F[1] &= cl; F[4] &= cl; F[7] &= cl; F[10] &= cl;F[13] &= cl; F[16] &= cl;F[19] &= cl;F[25] &= cl;
		}
		CompF[22] = F[22];
	}		 
 	if (CompF[23] != F[23] && F[23]>>27) {	UPD(23,21,22)
		if((F[23] >> 27) != S) { //  new single(s) not a key sequence
			F[23] &= S << 27 | BIT_SET_27; 			cl = ~(F[23] & TblRowMask[S]);
			F[2] &= cl; F[5] &= cl; F[8] &= cl; F[11] &= cl;F[14] &= cl; F[17] &= cl;F[20] &= cl;F[26] &= cl;
		}
		CompF[23] = F[23];
	}		 
  	if (CompF[24] != F[24] && F[24]>>27) {	UPD(24,25,26)
		if((F[24] >> 27) != S) { //  new single(s) not a key sequence
			F[24] &= S << 27 | BIT_SET_27; 	cl = ~(F[24] & TblRowMask[S]);
			F[0] &= cl; F[3] &= cl; F[6] &= cl; F[9] &= cl;F[12] &= cl; F[15] &= cl;F[18] &= cl;F[21] &= cl;
		}
		CompF[24] = F[24];
	}		 
 	if (CompF[25] != F[25] && F[25]>>27) {	UPD(25,24,26)
		if((F[25] >> 27) != S) { //  new single(s) not a key sequence
			F[25] &= S << 27 | BIT_SET_27; 			cl = ~(F[25] & TblRowMask[S]);
			F[1] &= cl; F[4] &= cl; F[7] &= cl; F[10] &= cl;F[13] &= cl; F[16] &= cl;F[19] &= cl;F[22] &= cl;
		}
		CompF[25] = F[25];
	}		 
 	if (CompF[26] != F[26] && F[26]>>27) {	UPD(26,24,25)
		if((F[26] >> 27) != S) { //  new single(s) not a key sequence
			F[26] &= S << 27 | BIT_SET_27; 			cl = ~(F[26] & TblRowMask[S]);
			F[2] &= cl; F[5] &= cl; F[8] &= cl; F[11] &= cl;F[14] &= cl; F[17] &= cl;F[20] &= cl;F[23] &= cl;
		}
		CompF[26] = F[26];
	}		 
  }
  return 1;
}

#define ISP(n) if((F[n]&(1<<27)) && (BitCount[F[n]&0x1ff]<3)){Guess(n,0);return;} \
if((F[n]&(1<<28)) && (BitCount[(F[n]>>9)&0x1ff]<3)){Guess(n,1);return;}\
if((F[n]&(1<<29)) && (BitCount[(F[n]>>18)&0x1ff]<3)){Guess(n,2);return;} 
 
 void GAME::Guess(){
	 // try pair in row, the most common guess (done in priority)

	ISP(0) ISP(1) ISP(2) ISP(3) ISP(4) ISP(5) ISP(6) ISP(7) ISP(8) ISP(9)
	ISP(10) ISP(11) ISP(12) ISP(13) ISP(14) ISP(15) ISP(16) ISP(17) ISP(18) ISP(19)
	ISP(20) ISP(21) ISP(22) ISP(23) ISP(24) ISP(25) ISP(26)
	 // try now triplet in row or find smallest size
	 // check also for solution found

	 int Least=10,block_least,row_least_num,all_solved_rows=0;
	 for (int i=0; i < 27; i++)   {
		 int ww=F[i],not_solved_rows=ww>>27;
		 all_solved_rows |= not_solved_rows;
		 if(not_solved_rows & 1){
			 int row=ww & 0x1ff,ncells=BitCount[row];
			 if(ncells<4) {Guess(i,0);return;}  
			 if(ncells<Least){
				 Least=ncells; block_least=i;
				 row_least_num=0;
			 }
		 }
 		 if(not_solved_rows & 2){
			 int row=(ww>>9) & 0x1ff,ncells=BitCount[row];
			 if(ncells<4) {Guess(i,1);return;}  
			 if(ncells<Least){
				 Least=ncells; block_least=i;
				 row_least_num=1;
			 }
		 }
  		 if(not_solved_rows & 4){
			 int row=(ww>>18) & 0x1ff,ncells=BitCount[row];
			 if(ncells<4) {Guess(i,2);return;} 
			 if(ncells<Least){
				 Least=ncells; block_least=i;
				 row_least_num=2;
			 }
		 }
	 }
	 if(!all_solved_rows){// this is a solution
		 if(glb.zsol && (!glb.nsol)) // store the first solution
			 SetKnown(glb.zsol);
		 glb.nsol++;
		 return;
	 }
	 // can also try pair in box
	 if(Least<3) return; // safety test, should never be
	 // no pair found use the first shortest in row
	 Guess(block_least,row_least_num);
 }


 void GAME::Guess(int ibf,int irow){// guess a row with several candidates
	 int ww=F[ibf],row=(ww>>(TblMult9[irow])) & 0x1ff,
		 dig=Tbldiv3[ibf],
		 startrow=Tblstartblock[ibf]+TblMult9[irow];
	 while(1){ // loop for any number of candidates
		 int rcell=Tblfirst0_8[row];

		 GAME & mynext = glb.mytable[index+1]; // start next guess
		 mynext=(*this);
		 mynext.index++;
		 mynext.Seta(dig,rcell+startrow);
		 mynext.ComputeNext();

		 if(glb.nsol>glb.lim) return;
		 row ^= (1<<rcell);
		 if(!row) return;
	 }
 }

 
void GAME::Seta(int digit,int cell){ // single in cell
	int sbl=TblMult3[digit] + TblBoard_Block[cell],
		soff=Tbloffset[cell],
		cl  = BIT_SET_30^(1<<soff);
	byte	*wb=TblOtherSameBand[sbl];
	F[(*wb++)] &= cl; F[(*wb++)] &= cl; 
	F[(*wb++)] &= cl; F[(*wb++)] &= cl;
	F[(*wb++)] &= cl; F[(*wb++)] &= cl;
	F[(*wb++)] &= cl;F[(*wb)] &= cl;

	// update band and other bands same digit
	cl  = BIT_SET_30^(0x40201<<TblMod9[soff]); // now 3 cells
	F[TblAnother1[sbl]]&= cl ; // clean column
	F[TblAnother2[sbl]]&= cl ;

	// Clean the row and the box in the band band containing the cell

	int indoff=Tblofftorow[soff];
	F[sbl] &= (BIT_SET_30 ^  // next must be cleared in the band
		 (  (((0x1ff<<TblMult9[indoff]) |  // row
		      (0x1C0E07 << TblMult3[ Tblofftobox[soff]])   )// or box
			 ^ (1<<soff) )// except assigned
			 |  (1  <<  (27+indoff) ) ) );//  row set assigned
}



void GAME::SetKnown(char * zs){	
	strcpy (zs,empty_puzzle);
	for(int i=0;i<27;i++) {
		int arows=F[i]>>27;
		if((arows & 7) ==7) continue; // not assigned
		for(int j=0;j<3;j++) if(!( arows & (1<<j) ) ) {
			int row=(F[i]>>TblMult9[j]) & 0x1ff,
				cell=TblBitIndex[row]+Tblstartblock[i]+TblMult9[j] ;
			zs[cell]= Tbldiv3[i] + '1';
		}
	}
}

int GAME::CheckValidityQuick(char *puzzle,int igame){
	glb.nsol=0;
	glb.lim=1;
	InitSudoku(puzzle,igame);
	ComputeNext ();
	return GAME::glb.nsol;
}

int GAME::CheckValiditySolver(char *puzzle,int igame){
	glb.nsol=0;
	glb.lim=1;
	InitSudoku(puzzle,igame);
	GAME & mynext = glb.mytable[1]; // keep game[0] at init status
	mynext=(*this);
	mynext.index++;
	mynext.ComputeNext ();
	return GAME::glb.nsol;
}

int GAME::DoUpdate(){
	if(!Update()) return 0; // game locked
	for(int i=0;i<27;i++) if(F[i] & (7<<27)) return 2; // not solved
	return 1; // solved
}

word GAME::GetFreeDigits(int cell){
	word digs=0;
	int soff=Tbloffset[cell];
	int indoff=Tblofftorow[soff],
		bitoffset=1<<soff,
		rowunassigned=1<<(27+indoff);
	for(int i=0;i<9;i++){
		int sbl=TblMult3[i] + TblBoard_Block[cell];
		if(F[sbl]&bitoffset)
			if(F[sbl] & rowunassigned) digs |= (1<<i);
			else return 0; // if assigned, return no digit free
	}
	return digs;
}


void GAME::Band_to_Myd(PM_DATA & myd){ // study a move from band to myd
	for(int i=0;i<9;i++)for(int j=0;j<27;j++) myd.dig_reg[i][j].f=0;
	for(int i=0;i<81;i++) myd.dig_cells[i].f=0;

	for(int sdig=0;sdig<9;sdig++) {
		for(int iband=0,srow=0;iband<3;iband++){
			int sbl=TblMult3[sdig]+iband;
			for(int irr=0;irr<3;irr++,srow++){
				int vrow=(F[sbl ]>> TblMult9[irr]) & 0x1ff;
				if(F[sbl] & (1<<(27+irr)))// not assigned, transfert to others
					myd.Do_Zhou_Row_Transfer(sdig,srow, vrow);			
				else{ // assigned
					int cell=TblMult9[srow]+TblBitIndex[vrow];
					myd.Do_Zhou_Assign(sdig, cell);
				} 				  
			}
		}
	}
}

void GAME::StdClean(int dig , int cell){ // clean a candidate from the standard process
	int sbl=TblMult3[dig]+TblBoard_Block[cell],
		soff=Tbloffset[cell];
//	EE.E("game clean "); EE.E(dig+1), EE.Enl(cellsFixedData[cell].pt);
	F[sbl] &=  (BIT_SET_30^(1<<soff));
}

word TblKillKnown[8] ={0,0,0,0x3f,0,0x1c7,0x1f8,0x1ff}; // minirows unknown
word TblShrinkKillRow[3]={0x1f8,0x1c7,0x3f};
word TblShrinkBox[3] = {0x49,0x92,0x124};

int GAME::Pointing17(){
	int ir=0;
	for(int ibl=0;ibl<27;ibl++){
		if(F[ibl]==CompF[ibl] || (!(F[ibl]>>27))) continue;
		int X=F[ibl], 
			shrink=(TblShrinkMask[X & 0x1FF] )|
			(TblShrinkMask[ (X>>9) & 0x1FF]<<3) |
			(TblShrinkMask[ (X>>18) & 0x1FF]<<6);
		shrink &= TblKillKnown[X>>27]; // forget known rows

		int	newminir=TblNewBoxRow[shrink];
		if(newminir) { // new box row found
			for(int ibb=0;ibb<3;ibb++){ //search each row
				int neww=newminir & (7<<(3*ibb));
				if(BitCount[neww]-1) continue ;
				int iminir=Tblfirst0_8[neww],
					row=iminir/3;
				int shrinkw= shrink & TblShrinkKillRow[row];
				for(int ibox=0;ibox<3;ibox++){
					int bb=shrinkw & TblShrinkBox[ibox];
					if(BitCount[bb]-1) continue;
					int iminirow=TblBitIndex[bb],
						minirow=(X>>(3*iminirow)) & 7;
					if(BitCount[minirow]-1) continue;
					// single to assign
					int dig=Tbldiv3[ibl],
						cell=Tblstartblock[ibl]+ TblBitIndex[minirow]+(3*iminirow) ;
					pm_go.zpmd[0].AssignStandard(dig,cell);
					ir++;
				}
			}
		}
		int S0=TblColumnSingleinBox[(X | (X >> 9) | (X >> 18)) & 0x1FF]; 
		if(S0){ // possible assigned in another box if new
				for(int ialt=0;ialt<2;ialt++){
				int ibl2=(ialt)?TblAnother2[ibl]:TblAnother1[ibl],
					Y=F[ibl2],
					S1 = ((Y | (Y >> 9) | (Y >> 18)) & 0x1FF),
					S01=S0 & S1;
				if(!S01) continue; // old locked in box search each box
				for(int ibb=0;ibb<3;ibb++){
					int S01b = S01 & (7<<(3*ibb));
					if(BitCount[S01b]-1) continue ;
					int ibox=Tbldiv3[Tblfirst0_8[S01b]],
						mask=TblMaskSingle[S01b]& TblBoxMask[ibox],
						shift=3*ibox;
					S01 ^= (1<<ibox); // Clear the bit
					int Z=Y&mask; // now remainning candidates in Box
					int box=((Z>>shift) & 7) |
						    (( Z>>(shift+6)) & 0x38) |
							(( Z>>(shift+12)) & 0x1c0); 
					if(BitCount[box]-1) continue;
					// single to assign
					int dig=Tbldiv3[ibl],cell=Tblstartblock[ibl2],
						rel_pos=TblBitIndex[box]; 
					cell+= 9*Tbldiv3[rel_pos];
					cell += rel_pos % 3+(3*ibox);
					pm_go.zpmd[0].AssignStandard(dig,cell);
					ir++;
				}
			}
		}
	}
	return ir;
}

int GAME::Pointing26(){
	int ir=0;
	for(int ibl=0;ibl<27;ibl++){
		if(F[ibl]==CompF[ibl] || (!(F[ibl]>>27))) continue;
		int X=F[ibl], 
			shrink=(TblShrinkMask[X & 0x1FF] )|
			(TblShrinkMask[ (X>>9) & 0x1FF]<<3) |
			(TblShrinkMask[ (X>>18) & 0x1FF]<<6),
			newminir=TblNewBoxRow[shrink];
		if(newminir) { // new box row found
			X &= TblMask26row[Tblfirst0_8[newminir]];
			if(Fupdate(X,ibl)){
				ir++;
			}
		}

		int S0=TblColumnSingleinBox[(X | (X >> 9) | (X >> 18)) & 0x1FF]; 
		if(S0){ // possible assigned in another box if new
			for(int ialt=0;ialt<2;ialt++){
				int ibl2=(ialt)?TblAnother2[ibl]:TblAnother1[ibl],
					Y=F[ibl2],
					S1 = ((Y | (Y >> 9) | (Y >> 18)) & 0x1FF),
					S01=S0 & S1;
				if(!S01) continue; // old locked in box
				Y&=TblMaskSingle[S01]; // now remainning candidates in Box
				if (Fupdate(Y,ibl2)){
					ir++;
				}
			}
		}
	}
	return ir;
}

int GAME::Fupdate(int X,int ibl){
	int Y=F[ibl];
	if(!glb.onlyone) F[ibl]=X; //don't pile results if onlyone 
	Y&=BIT_SET_27;
	X&=BIT_SET_27;
	if(Y==X) return 0;
	Y ^= X; // candidates to clean; 
	BF81 & myelim = pm_go.pmelims.bfc[Tbldiv3[ibl]],
		rmyelim=myelim;
	myelim.OrBand(Y,Tblmod3[ibl]);
	if(myelim==rmyelim) return 0;
	return 1;
}

int GAME::UpdateCycle(int onlyone){ // serate mode er>30 do as much as possible
	// don't call if singles can be solved
	glb.onlyone=onlyone;
  int Shrink=1,S,C1,C2,ir=0;
  while(Shrink){  // loop control provisoire
	Shrink=0;
	for(int ibl=0;ibl<27;ibl++){
		if (CompF[ibl] == F[ibl]  ) continue;
		int X=F[ibl];
		Shrink=TblShrinkMask[X & 0x1FF] |
			TblShrinkMask[ (X>>9) & 0x1FF]<<3 |
			TblShrinkMask[ (X>>18) & 0x1FF]<<6;
		X &=TblComplexMask[Shrink]; // valid, so can not be null
		if(Fupdate(X,ibl)){
				ir++;
		}

		int ibl1=TblAnother2[ibl],ibl2=TblAnother1[ibl],
			Y=F[ibl1] ,Z=F[ibl2];
		int S0=(X | (X >> 9) | (X >> 18)) & 0x1FF;
		C1=S0 | ((Y | (Y >> 9) | (Y >> 18)) & 0x1FF),
		C2=S0 | ((Z | (Z >> 9) | (Z >> 18)) & 0x1FF); 
		Z &= TblMaskSingle[S0] & TblMaskDouble[C1];  
		Y &= TblMaskSingle[S0] & TblMaskDouble[C2]; 
		if((Fupdate(Y,ibl1)+Fupdate(Z,ibl2))){
				ir++;
		}
		S = TblRowUniq[TblShrinkSingle[Shrink] & TblColumnSingle[S0]];
		if((X >> 27) != S) { //  new single(s) not a key sequence
			int bitssing=(X >> 27) ^ S; // new single if one ... to 111
			F[ibl] &= S << 27 | BIT_SET_27; 	
			for(int irow=0;irow<3;irow++)if(bitssing & (1<<irow)){
				int dig=Tbldiv3[ibl],cell=Tblstartblock[ibl]+9*irow; 
				cell += Tblfirst0_8[(X>>(9*irow)) & 0x1ff];
				pm_go.zpmd[0].AssignStandard(dig,cell);
				ir++;
			}
		}
		CompF[ibl] = F[ibl];
	}
//	EE.Enl("end of update cycle");
//	Debug(1);
	if(onlyone) break;
  }
return ir;
}

word GAME::Go_One_Floor10(){// must be in game[10} 
	*this=game[0];
	index=10;
	word active=0;
	for(int i=0;i<9;i++){
		glb.F_or[0]=glb.F_or[1]=glb.F_or[2]=0;
		glb.a=3*i; glb.b=glb.a+1; glb.c=glb.b+1;

		GuessFloor(glb.a,glb.b,glb.c);
		glb.F_or[0] ^=(F[glb.a] & BIT_SET_27);
		glb.F_or[1] ^= (F[glb.b] & BIT_SET_27);
		glb.F_or[2] ^=  (F[glb.c] & BIT_SET_27);

		glb.elims.bfc[i].SetAll_0();
		glb.elims.bfc[i].LoadZhou(glb.F_or);
		if(glb.elims.bfc[i].IsNotEmpty())
		   active |= (1<<i);
	}
	return active;
}
 
 int GAME::UpdateFloor(int a,int b,int c){
  int Shrink=1,S,C1,C2;
  while(Shrink){ 
 	Shrink=0;
 	if (CompF[a] != F[a] && F[a]>>27) {	UPD(a,b,c)
		F[a] &= S << 27 | BIT_SET_27;  
		CompF[a] = F[a];
	}		 
 	if (CompF[b] != F[b] && F[b]>>27) {		UPD(b,a,c)
		F[b] &= S << 27 | BIT_SET_27; 	
		CompF[b] = F[b];
	}		 
 	if (CompF[c] != F[c] && F[c]>>27) {	UPD(c,a,b)
		F[c] &= S << 27 | BIT_SET_27; 
		CompF[c] = F[c];
	}		 
  }
  return 1;
}

#define ISPF1(n,m) if((F[n]&(1<<27)) && (BitCount[F[n]&0x1ff]<m))\
 {GuessFloor(n,0);return;} \
if((F[n]&(1<<28)) && (BitCount[(F[n]>>9)&0x1ff]<m))\
 {GuessFloor(n,1);return;}\
if((F[n]&(1<<29)) && (BitCount[(F[n]>>18)&0x1ff]<m))\
 {GuessFloor(n,2);return;} 
 
 void GAME::GuessFloor(int a,int b,int c){
	 if(!((F[a] | F[b] | F[c])>>27) ){ //this is a solution
		 glb.F_or[0]  |= F[a];
		 glb.F_or[1]  |= F[b];
		 glb.F_or[2]  |= F[c];
		 return;
	 }
	ISPF1(a,3) ISPF1(b,3) ISPF1(c,3)  // try pair 
	ISPF1(a,10) ISPF1(b,10) ISPF1(c,10)  // if not, any row
 } 
 
 void GAME::GuessFloor(int ibf,int irow){// guess a row with several candidates
	 int ww=F[ibf],row=(ww>>(TblMult9[irow])) & 0x1ff,
		 dig=Tbldiv3[ibf],
		 startrow=Tblstartblock[ibf]+TblMult9[irow];
	 while(1){ // loop for any number of candidates
		 int rcell=Tblfirst0_8[row];

		 GAME & mynext = glb.mytable[index+1]; // start next guess
		 mynext=(*this);
		 mynext.index++;
		 mynext.SetaFloor(dig,rcell+startrow);
		 if(mynext.UpdateFloor(glb.a,glb.b,glb.c))
			 mynext.GuessFloor(glb.a,glb.b,glb.c);
		 row ^= (1<<rcell);
		 if(!row) return;
	 }
 } 

void GAME::SetaFloor(int digit,int cell){ // single in cell
	int sbl=TblMult3[digit] + TblBoard_Block[cell],
		soff=Tbloffset[cell],
		cl  =  BIT_SET_30^(0x40201<<TblMod9[soff]); // now 3 cells
	F[TblAnother1[sbl]]&= cl ; // clean column
	F[TblAnother2[sbl]]&= cl ;

	// Clean the row and the box in the band band containing the cell

	int indoff=Tblofftorow[soff];
	F[sbl] &= (BIT_SET_30 ^  // next must be cleared in the band
		 (  (((0x1ff<<TblMult9[indoff]) |  // row
		      (0x1C0E07 << TblMult3[ Tblofftobox[soff]])   )// or box
			 ^ (1<<soff) )// except assigned
			 |  (1  <<  (27+indoff) ) ) );//  row set assigned
}

